home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Sample Controls / Events / CEventSend.cpp < prev    next >
Encoding:
Text File  |  1996-12-16  |  9.4 KB  |  429 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //
  3. //    CEventSend.cpp                ©1996 Microsoft Corporation All rights reserved.
  4. //
  5. // =================================================================================
  6.  
  7. #include "ocheaders.h"
  8. #include <LArray.h>
  9. #include "CConnectionPoint.h"
  10. #include "CCPContainer.h"
  11. #include "CEventSend.h"
  12.  
  13. /************* Local EventSend defines ****************/
  14. #define NUM_CONNECTIONS    1    // This control only has one connection point
  15. #define    kIDLen            256    // max number of characters in the control ID (name)
  16. //
  17. //  CEventSend::CEventSend
  18. //
  19.  
  20. CEventSend::CEventSend(void) : CBaseControl()
  21. {
  22.     CCPContainer*        containerObj = nil;
  23.  
  24.     mOwnedFoci = EmptyFocusSet;
  25.     
  26.     // No message to display    
  27.     PLstrcpy(mMessage, "\p");
  28.  
  29.     mIdP = NULL;
  30.     mLastMouseUpTime = ::TickCount() - ::GetDblTime();
  31.  
  32.     // Create the new connection point container object
  33.     containerObj = new CCPContainer(NUM_CONNECTIONS);
  34.     
  35.     // Snag the interface pointer
  36.     if ( containerObj )
  37.         containerObj->QueryInterface(IID_IConnectionPointContainer, &mCPContainerP);
  38.     
  39.     // if we have a container object, allocate the connection points
  40.     if ( mCPContainerP )
  41.         // We support 1 connection point
  42.         containerObj->AddConnectionPoint(IID_IStandardEvents);
  43. }
  44.  
  45.  
  46. //
  47. //  CEventSend::~CEventSend
  48. //
  49.  
  50. CEventSend::~CEventSend(void)
  51. {
  52.     if (mIdP)
  53.         delete [] mIdP;
  54. }
  55.  
  56.  
  57.  
  58. //
  59. //  CEventSend::FireEvent
  60. //
  61.  
  62. STDMETHODIMP
  63. CEventSend::FireEvent(REFIID inRefID, Int32 inEventID, PlatformEvent* inEvent)
  64. {
  65.     IEnumConnectionPoints*    enumCP;
  66.     IEnumConnections*        enumC;
  67.     CONNECTDATA                connectData;
  68.     IUnknown*                eventTarget;
  69.     IConnectionPoint*        connectionPoint;
  70.     
  71.     // Get an enumerator for the connection points
  72.     if ( SUCCEEDED(mCPContainerP->EnumConnectionPoints(&enumCP)) )
  73.     {
  74.         // Loop through all the connection points for this control
  75.         while ( enumCP->Next(1, &connectionPoint, nil) == NOERROR )
  76.         {
  77.             // Get all the connections for this connection point
  78.             if ( SUCCEEDED( connectionPoint->EnumConnections(&enumC) ))
  79.             {
  80.                 // Loop through all the connections for this connection point    
  81.                 while ( enumC->Next(1, &connectData, nil) == NOERROR )
  82.                 {
  83.                     // Get the interface implementation for this connection
  84.                     // if successful, fire the event
  85.                     if ( SUCCEEDED( connectData.pUnk->QueryInterface(inRefID, (void**) &eventTarget) ))
  86.                         FireOneEvent(inRefID, inEventID, eventTarget, inEvent);
  87.                 }
  88.                 
  89.                 // Release the enumerator
  90.                 enumC->Release();
  91.             }
  92.         }
  93.         
  94.         enumCP->Release();
  95.     }
  96.     
  97.     return S_OK;
  98. }
  99.  
  100.  
  101. //
  102. //  CEventSend::FireOneEvent
  103. //
  104.  
  105. STDMETHODIMP
  106. CEventSend::FireOneEvent(REFIID inRefID, Int32 inEventID, IUnknown* inEventTarget, PlatformEvent* inEvent)
  107. {
  108. #pragma unused (inRefID)
  109.     IStandardEvents*    target = (IStandardEvents*) inEventTarget;
  110.     IUnknown*            unk;
  111.     
  112.     this->QueryInterface(IID_IUnknown, (void**) &unk);
  113.     
  114.     switch ( inEventID )
  115.     {
  116.         case DISPID_DBLCLICK:
  117.             target->OnDoubleClick(unk, inEvent);
  118.             break;
  119.  
  120.         case DISPID_KEYDOWN:
  121.             target->OnKeyDown(unk, inEvent);
  122.             break;
  123.  
  124.         case DISPID_AUTOKEY:
  125.             target->OnAutoKey(unk, inEvent);
  126.             break;
  127.  
  128.         case DISPID_KEYUP:
  129.             target->OnKeyUp(unk, inEvent);
  130.             break;
  131.  
  132.         case DISPID_MOUSEDOWN:
  133.             target->OnMouseDown(unk, inEvent);
  134.             break;
  135.  
  136.         case DISPID_MOUSEUP:
  137.             target->OnMouseUp(unk, inEvent);
  138.             break;
  139.     }
  140.     
  141.     return S_OK;
  142. }
  143.  
  144.  
  145. //
  146. //  CEventSend::IControl::Draw
  147. //
  148.  
  149. STDMETHODIMP
  150. CEventSend::Draw(DrawContext* inContext)
  151. {
  152.     Char8        id[kIDLen];
  153.     FontInfo    fInfo;
  154.     Int16        curX;
  155.     Int16        curY;
  156.     RgnHandle    saveClipRgn;
  157.     Rect        controlRect, newClipRect;
  158.     Boolean8    overlap = false;
  159.     
  160.     if (inContext->DrawAspect != DVASPECT_CONTENT)
  161.         return DV_E_DVASPECT;
  162.  
  163.     // Set the font and size    
  164.     ::TextFont(applFont);
  165.     ::TextFace(0);
  166.     ::TextMode(srcCopy);
  167.     ::TextSize(12);
  168.     ::GetFontInfo(&fInfo);
  169.  
  170.     // Erase the area and outline the frame (thicker if in focus)
  171.     ::EraseRect(&inContext->Location);
  172.     if (mOwnedFoci & KeyboardFocus) {
  173.         ::PenSize(2, 2);
  174.     }
  175.     else {
  176.         ::PenSize(1, 1);
  177.     }
  178.     ::FrameRect(&inContext->Location);
  179.  
  180.     // Save the current clip
  181.     saveClipRgn = ::NewRgn();
  182.     ::GetClip(saveClipRgn);
  183.  
  184.     controlRect = inContext->Location;
  185.     ::InsetRect(&controlRect, 3, 3);
  186.     overlap = SectRect(&controlRect, &((*saveClipRgn)->rgnBBox), &newClipRect);
  187.  
  188.     if (overlap)
  189.     {
  190.         // Reset the clip
  191.         ::ClipRect(&newClipRect);
  192.     }
  193.  
  194.     curX = inContext->Location.left+4;
  195.     curY = inContext->Location.top+4;
  196.  
  197.     // Draw the control id (name) on the first line    
  198.     curY += fInfo.ascent;
  199.     ::MoveTo(curX, curY);
  200.     GetID(kIDLen, id);
  201.     ::DrawText(id, 0, strlen(id));
  202.     
  203.     // Draw the message on the second line
  204.     curY += fInfo.ascent + fInfo.descent + fInfo.leading;
  205.     ::MoveTo(curX, curY);
  206.     ::DrawString(mMessage);
  207.         
  208.     if (overlap)
  209.     {
  210.         // Restore the clip
  211.         ::SetClip(saveClipRgn);
  212.     }
  213.     ::DisposeRgn(saveClipRgn);
  214.  
  215.     return S_OK;
  216. }
  217.  
  218.  
  219. //
  220. //  CEventSend::IControl::GetID
  221. //
  222.  
  223. STDMETHODIMP
  224. CEventSend::GetID(Int32 inBufferSize, Char8* outID)
  225. {
  226.     if (mIdP)
  227.     {
  228.         Int32    IDLen = strlen(mIdP);
  229.  
  230.         if (IDLen > --inBufferSize)
  231.             IDLen = inBufferSize;
  232.  
  233.         ::BlockMove(mIdP, outID, IDLen);
  234.         *(outID + IDLen) = '\0';
  235.     }
  236.     else
  237.         return CBaseControl::GetID(inBufferSize, outID);
  238.  
  239.     return S_OK;
  240. }
  241.  
  242.  
  243. //
  244. //  CEventSend::IControl::DoMouse
  245. //
  246.  
  247. STDMETHODIMP
  248. CEventSend::DoMouse(MouseEventType inMouseET, PlatformEvent* inEvent)
  249. {
  250.     Boolean            doInval = false;
  251.  
  252.     switch (inMouseET)
  253.     {
  254.         case MouseDown:
  255.             if (( mOwnedFoci & KeyboardFocus ) ||
  256.                 (mContainerSiteP->RequestFocus(true, KeyboardFocus) == S_OK &&
  257.                     FocusSet(mOwnedFoci = FocusSet(mOwnedFoci | KeyboardFocus)) != EmptyFocusSet))
  258.             {
  259.                 PLstrcpy(mMessage, "\pmouseDown");
  260.                 doInval = true;
  261.                 FireEvent(IID_IStandardEvents, DISPID_MOUSEDOWN, inEvent);
  262.                 
  263.                 // Was this soon enough after the last mouse up to be a double-click?
  264.                 if ((inEvent->when - mLastMouseUpTime) <= ::GetDblTime())
  265.                 {
  266.                     PLstrcpy(mMessage, "\pdoubleClick");
  267.                     FireEvent(IID_IStandardEvents, DISPID_DBLCLICK, inEvent);
  268.                 }
  269.             }
  270.             break;
  271.         
  272.         case MouseUp:
  273.             if (mOwnedFoci & KeyboardFocus)
  274.             {
  275.                 mLastMouseUpTime = inEvent->when;
  276.                 PLstrcpy(mMessage, "\pmouseUp");
  277.                 doInval = true;
  278.                 FireEvent(IID_IStandardEvents, DISPID_MOUSEUP, inEvent);
  279.             }
  280.             break;
  281.     }
  282.  
  283.     // Invalidate the position rectangle so we'll get redrawn
  284.     if (doInval) 
  285.     {
  286.         InvalAllContexts();
  287.     }
  288.  
  289.     return S_OK;
  290. }
  291.  
  292.  
  293. //
  294. //  CEventSend::IControl::DoKey
  295. //
  296.  
  297. STDMETHODIMP
  298. CEventSend::DoKey(KeyEventType inKeyET, Char8 inChar, PlatformEvent* inEvent)
  299. {
  300.     Boolean    doInval = false;
  301.  
  302.     switch (inKeyET)
  303.     {
  304.         case KeyDown:
  305.             // if we have the focus, handle the key down
  306.             if ( mOwnedFoci & KeyboardFocus )
  307.             {
  308.                 PLstrcpy(mMessage, "\pkeyDown: ");
  309.                 // Display the key pressed in the message
  310.                 mMessage[0]++;
  311.                 mMessage[mMessage[0]] = inChar;
  312.                 doInval = true;
  313.                 FireEvent(IID_IStandardEvents, DISPID_KEYDOWN, inEvent);
  314.             }
  315.             break;
  316.             
  317.         case AutoKey:
  318.             // if we have the focus, handle the key down
  319.             if ( mOwnedFoci & KeyboardFocus )
  320.             {
  321.                 PLstrcpy(mMessage, "\pautoKey: ");
  322.                 // Display the key pressed in the message
  323.                 mMessage[0]++;
  324.                 mMessage[mMessage[0]] = inChar;
  325.                 doInval = true;
  326.                 FireEvent(IID_IStandardEvents, DISPID_AUTOKEY, inEvent);
  327.             }
  328.             break;
  329.             
  330.         case KeyUp:
  331.             // if we have the focus, handle the key up
  332.             if ( mOwnedFoci & KeyboardFocus )
  333.             {
  334.                 PLstrcpy(mMessage, "\pkeyUp: ");
  335.                 // Display the key pressed in the message
  336.                 mMessage[0]++;
  337.                 mMessage[mMessage[0]] = inChar;
  338.                 doInval = true;
  339.                 FireEvent(IID_IStandardEvents, DISPID_KEYUP, inEvent);
  340.             }
  341.             break;
  342.     }
  343.  
  344.     // Invalidate the position rectangle so we'll get redrawn
  345.     if (doInval) 
  346.     {
  347.         InvalAllContexts();
  348.     }
  349.  
  350.     return S_OK;
  351. }
  352.  
  353.  
  354. //
  355. //  CEventSend:IControl:SetFocus    
  356. //
  357.  
  358. STDMETHODIMP
  359. CEventSend::SetFocus(FocusCommand inCommand, FocusSet inFocus)
  360. {
  361.     DrawContext theContext = {BeginPortType};
  362.     ErrorCode    theResult = S_OK;
  363.     FocusSet    origOwnedFoci = mOwnedFoci;
  364.  
  365.     //    a TakeNext or TakePrev if we don't have the focus, means take it
  366.     if ((inCommand == TakeNextCommand || inCommand == TakePrevCommand) && !mOwnedFoci)
  367.     {
  368.         //     if the container is offering us the one focus we want, take all of them
  369.         if (inFocus & KeyboardFocus)
  370.             mOwnedFoci = inFocus;
  371.         else
  372.         //    otherwise, say no thanks
  373.             theResult = E_FAIL;
  374.     }
  375.     //    a TakeNext or a TakePrev on a control which doesn't embed and has the focus should fail
  376.     else if (inCommand == TakeNextCommand || inCommand == TakePrevCommand)
  377.     {
  378.         theResult = E_FAIL;
  379.     }
  380.     //    we're being asked/told to release our foci - always comply
  381.     else // if (Spec == ReleaseRequest || Spec == ReleaseCommand)
  382.     {
  383.         if (inFocus & mOwnedFoci != inFocus)
  384.             DebugStr("\pWhat are they doing asking to release foci we don't have?");
  385.  
  386.         mOwnedFoci = FocusSet(mOwnedFoci & ~inFocus);    //    really easy for us
  387.     }
  388.     
  389.     //    if the focus state of the keyboard changed
  390.     if ((origOwnedFoci & KeyboardFocus) != (mOwnedFoci & KeyboardFocus))
  391.     {
  392.         InvalAllContexts();
  393.     }
  394.     
  395.     return theResult;
  396. }
  397.  
  398. //  CEventSend::IPersistPropertyBag::Load
  399. //
  400.  
  401. STDMETHODIMP
  402. CEventSend::Load(IPropertyBag* PropertyBag, IErrorLog* ErrorLog)
  403. {
  404.     VARIANT        v;
  405.     Uint32        length;
  406.  
  407.     v.vt = VT_BSTR;
  408.     v.bstrVal = NULL;
  409.  
  410.     // try to load in the property.  if we can't get it, then leave
  411.     // things at their default.
  412.     //
  413.     PropertyBag->Read("id", &v, ErrorLog);
  414.     if (v.bstrVal)
  415.     {
  416.         length = *((Uint32*) v.bstrVal) ;
  417.         if (mIdP)
  418.             delete [] mIdP;
  419.         mIdP = new char[length + 1];
  420.         strcpy(mIdP, v.bstrVal + sizeof(Uint32));
  421.         CoTaskMemFree(v.bstrVal);
  422.     }
  423.  
  424.     return S_OK;
  425. }
  426.  
  427.  
  428.  
  429.